//
//  ZHEncrypt.m
//  ZHEncrypt
//
//  Created by luodp on 2018/1/12.
//  Copyright © 2018年 coreShield. All rights reserved.
//



#import "ZHEncrypt.h"
#import <CommonCrypto/CommonCrypto.h>

@implementation ZHEncrypt

+ (NSString *)encrypt:(NSString *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSString *)key CCAlgorithm:(CCAlgorithm)algorithm keySize:(NSUInteger)keySize{
    //    源数据
    NSData *originData = nil;
    if (encryptOperation == kCCDecrypt)
    {
        originData = [GTMBase64 decodeString:sText ];
    }
    else
    {
        originData = [sText dataUsingEncoding:NSUTF8StringEncoding];
        
    }
    
    NSData * resultData = [self encryptData:originData encryptOrDecrypt:encryptOperation key:[NSData dataWithBytes:[key UTF8String] length:key.length] CCAlgorithm:algorithm keySize:keySize];
    NSString * result = nil;
    if (resultData)
    {
        if (encryptOperation == kCCDecrypt)
        {
            result = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding] ;
        }
        else
        {
//            NSLog(@"%@", resultData);
            result = [GTMBase64 stringByEncodingData:resultData];
        }
    }
//    NSLog(@"%@",result);
    return result;
}

+ (NSData *)encryptData:(NSData *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSData *)key CCAlgorithm:(CCAlgorithm)algorithm keySize:(NSUInteger)keySize{
    const void *vplainText;
    size_t plainTextBufferSize;
    if (encryptOperation == kCCDecrypt)
    {
        plainTextBufferSize = [sText length];
        vplainText = [sText bytes];
    }
    else
    {
        plainTextBufferSize = [sText length];
        vplainText = (const void *)[sText bytes];
    }
    
    void *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t movedBytes = 0;
    NSUInteger blockSize = [self blockSize:algorithm];
    bufferPtrSize = (plainTextBufferSize + blockSize) & ~(blockSize - 1);
    bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
    memset((void *)bufferPtr, 0x0, bufferPtrSize);
    
    NSString *initVec = @"12345678";
    const void *vkey = (const void *) [key bytes];
    const void *vinitVec = (const void *) [initVec UTF8String];
    
    CCCryptorStatus ccStatus = CCCrypt(encryptOperation,
                                       algorithm,
                                       kCCOptionECBMode | kCCOptionPKCS7Padding,
                                       vkey,
                                       keySize,
                                       vinitVec,
                                       vplainText,
                                       plainTextBufferSize,
                                       (void *)bufferPtr,
                                       bufferPtrSize,
                                       &movedBytes);
//    NSLog(@"%d",ccStatus);
    NSData *result = nil;
    if (ccStatus == kCCSuccess)
    {
        if (encryptOperation == kCCDecrypt)
        {
            result = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
        }
        else
        {
            NSData *data = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
            result = [NSData dataWithData:data];
        }
    }
//    NSLog(@"%@",result);
    return result;
    
}
#pragma mark - data

+ (NSData *)encryptData:(NSData *)data encryptOrDecrypt:(CCOperation)encryptOperation key:(NSData *)key
{
    return [self encryptData:data encryptOrDecrypt:encryptOperation key:key CCAlgorithm:kCCAlgorithmDES keySize:kCCKeySizeDES];
}

+ (NSData *)DESEncryptWithData:(NSData *)data theKey:(NSData *)aKey
{
    return [self encryptData:data encryptOrDecrypt:kCCEncrypt key:aKey];
}

+ (NSData *)DESDecryptWithData:(NSData *)data theKey:(NSData *)aKey
{
    return [self encryptData:data encryptOrDecrypt:kCCDecrypt key:aKey];
}

+ (NSData *)DES3EncryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithm3DES keySize:kCCKeySize3DES];
}

+ (NSData *)DES3DecryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithm3DES keySize:kCCKeySize3DES];
}

+ (NSData *)AES128EncryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES128];
}

+ (NSData *)AES128DecryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES128];
}

+ (NSData *)AES256EncryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES256];
}

+ (NSData *)AES256DecryptWithData:(NSData *)data theKey:(NSData *)key{
    return [self encryptData:data encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES256];
}

#pragma mark - string

+ (NSString *)encrypt:(NSString *)sText encryptOrDecrypt:(CCOperation)encryptOperation key:(NSString *)key
{
    return [self encrypt:sText encryptOrDecrypt:encryptOperation key:key CCAlgorithm:kCCAlgorithmDES keySize:kCCKeySizeDES];
}

+ (NSString *)DESEncryptWithText:(NSString *)sText theKey:(NSString *)aKey
{
    return [self encrypt:sText encryptOrDecrypt:kCCEncrypt key:aKey];
}

+ (NSString *)DESDecryptWithText:(NSString *)sText theKey:(NSString *)aKey
{
    return [self encrypt:sText encryptOrDecrypt:kCCDecrypt key:aKey];
}

+ (NSString *)DES3EncryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithm3DES keySize:kCCKeySize3DES];
}

+ (NSString *)DES3DecryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithm3DES keySize:kCCKeySize3DES];
}

+ (NSString *)AES128EncryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES128];
}

+ (NSString *)AES128DecryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES128];
}

+ (NSString *)AES256EncryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCEncrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES256];
}

+ (NSString *)AES256DecryptWithText:(NSString *)stext theKey:(NSString *)key{
    return [self encrypt:stext encryptOrDecrypt:kCCDecrypt key:key CCAlgorithm:kCCAlgorithmAES128 keySize:kCCKeySizeAES256];
}

/**
 *  异或加密算法//加密算法就是解密算法
 *
 *  @param data 需要加密的字节流
 *  @param key        加密的key
 *
 *  @return 加密后的字节流
 */
+ (NSData *)XOREncodeData:(NSData *)data key:(NSData *)key {
    Byte *keyBytes = (Byte *)[key bytes];   //取关键字的Byte数组, keyBytes一直指向头部
    
    Byte *dataArray = (Byte *)[data bytes];  //取需要加密的数据的Byte数组
    
    for (long i = 0; i < [data length]; i++) {
//        Byte keyByte = keyBytes[(i % [key length])];
        dataArray[i] = dataArray[i] ^ keyBytes[(i % [key length])]; //然后按位进行异或运算
    }
    
    return data;
}

+ (NSInteger)blockSize:(CCAlgorithm)algorithm {
    switch (algorithm) {
        case kCCAlgorithmAES:
            return kCCBlockSizeAES128;
        case kCCAlgorithmDES:
            return kCCBlockSizeDES;
        case kCCAlgorithm3DES:
            return kCCBlockSize3DES;
        case kCCAlgorithmRC2:
            return kCCBlockSizeRC2;
        case kCCAlgorithmCAST:
            return kCCBlockSizeCAST;
            
        default:
            //            默认8字节
            return kCCBlockSizeDES;
            break;
    }
}


@end
